package com.heaven1949.tmall.common.core.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zhangjian
 */
public class DateUtil {

    public static final String FORMAT_BASE_DATE = "yyyy-MM-dd";
    public static final String NON_FORMAT_BASE_DATE = "yyyyMMdd";
    public static final String FORMAT_FULL_TIME = "yyyy-MM-dd HH:mm:ss";
    /**
     * 时间格式验证正则 20yy-MM-dd HH:mm
     */
    public static final String PATTERN_DATE_TIME = "^20\\d{2}\\-((0[1-9])|(1[0-2]))\\-(([0]?[1-9])|([12][0-9])|(3[01])) (([01][0-9])|(2[0-3]))\\:([0-5][0-9])$";

    /**
     * 时间格式验证正则 yyyy-MM-dd HH:mm:ss
     */
    public static final String PATTERN_FULL_TIME = "^\\d{4}(-|\\/)\\d{1,2}(-|\\/)\\d{1,2}\\s([01]?\\d|2[0-3]):[0-5]?\\d:[0-5]?\\d$";

    /**
     * 时间格式check 验证格式 yyyy-MM-dd HH:mm
     *
     * @param date 字符格式的时间
     * @return true 格式正确 false 格式错误
     * @author eleven
     */
    public static boolean matcherFormat(String date) {
        Pattern r = Pattern.compile(PATTERN_DATE_TIME);
        Matcher m = r.matcher(date);
        return m.matches();
    }

    /**
     * 时间格式check 验证格式（可外部传入）
     *
     * @param date    字符格式的时间
     * @param pattern 验证正则
     * @return true 格式正确 false 格式错误
     * @author eleven
     */
    public static boolean matcherFormat(String date, String pattern) {
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(date);
        return m.matches();
    }


    /**
     * 获取今天的时间日期  格式自传
     *
     * @param formatter
     * @return
     */
    public static Date getSystemDate(String formatter) {
        return string2Date(now().format(DateTimeFormatter.ofPattern(formatter)));

    }

    /**
     * 获取今天的时间日期  格式自传
     *
     * @param formatter
     * @return String
     */
    public static String getSystemDateToString(String formatter) {
        return now().format(DateTimeFormatter.ofPattern(formatter));

    }

    public static Date localDate2Date(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    public static Date string2Date(String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(FORMAT_BASE_DATE);
        LocalDate parse = LocalDate.parse(date, formatter);
        return localDate2Date(parse);
    }

    public static Integer string2Integer(String date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(FORMAT_BASE_DATE);
        LocalDate parse = LocalDate.parse(date, formatter);
        return Integer.valueOf(parse.format(DateTimeFormatter.ofPattern(NON_FORMAT_BASE_DATE)));
    }

    public static Integer today() {
        String format = LocalDate.now().format(DateTimeFormatter.ofPattern(NON_FORMAT_BASE_DATE));
        return Integer.parseInt(format);
    }

    public static String todayAsString() {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(NON_FORMAT_BASE_DATE));
    }

    public static String nowAsString() {
        return now().format(DateTimeFormatter.ofPattern(FORMAT_FULL_TIME));
    }

    public static LocalDateTime now() {
        return LocalDateTime.now(ZoneId.systemDefault());
    }

    public static Date localDateTime2Data(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static String nowTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

    /**
     * 今天是否在两个日期之间
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return true：在区间内
     */
    public static boolean between(Date start, Date end) {
        Date now = new Date();
        // now >= start && now <= end
        return (now.after(start) || now.equals(start)) && (now.after(end) || now.equals(end));
    }

    /**
     * 获取指定时间的字符串<br>
     * 获取前N天传-N <br>获取后N天传N <br>获取当天传0 <br>
     * ymd 等同 yyyy-MM-dd  <br> ymdhms 等同 yyyy-MM-dd HH:mm:ss
     *
     * @param date   日期
     * @param day    N值
     * @param format ymd、ymdhms、其他格式
     * @return 返回{format}格式的字符串
     */
    public static String specifiedDateToString(Date date, int day, String format) {

        DateFormat dateFormat = new SimpleDateFormat(format);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return dateFormat.format(calendar.getTime());
    }

    /**
     * date1=date2  返回0 <br>
     * date1在date2之前  返回-1<br>
     * date1在date2之后  返回1
     *
     * @param date1
     * @param date2
     * @param format 时间格式
     * @return
     */
    public static int compareDate(String date1, String date2, String format) {
        Date d1 = string2Date(date1, format);
        Date d2 = string2Date(date2, format);
        return d1.compareTo(d2);
    }

    /**
     * java.lang.String 类型日期转 java.util.Date
     *
     * @param date
     * @param format ymd 相当于 yyyy-MM-dd  ymdhms 相当于 yyyy-MM-dd HH:mm:ss
     * @return 返回{format}格式的日期
     */
    public static Date string2Date(String date, String format) {
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            return dateFormat.parse(date);
        } catch (Exception e) {
            throw new RuntimeException("日期转换失败");
        }
    }


    /**
     * java.util.Date 类型日期转 java.lang.String
     *
     * @param date
     * @return 返回{format}格式的字符串
     */
    public static String date2String(Date date, String format) {
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            return dateFormat.format(date);
        } catch (Exception e) {
            throw new RuntimeException("日期转换失败");
        }
    }

    /**
     * yyyyMMdd 转 yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static String stringToDate(String date) {
        try {
            Date format = new SimpleDateFormat("yyyyMMdd").parse(date);
            String dateString = new SimpleDateFormat("yyyy-MM-dd").format(format);
            return dateString;
        } catch (ParseException e) {
            throw new RuntimeException("日期转换失败");
        }
    }

    public static String localDate2String(LocalDate date) {
        return date.format(DateTimeFormatter.ofPattern(FORMAT_BASE_DATE));
    }

    /**
     * 时间戳转LocalDateTime
     *
     * @param timestamp
     * @return
     */
    public static LocalDateTime timestamp2LocalDatetime(Long timestamp) {
        return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
    }

    /**
     * 时间戳转Date
     *
     * @param timestamp
     * @return
     */
    public static Date timestamp2Date(Long timestamp) {
        return new Date(timestamp);
    }


    /**
     * 分钟转 xx天xx小时xx分钟
     *
     * @param minute
     * @return
     * @author Eleven
     * @date 2021-04-07 11:11
     */
    public static String turnDayHourMinuteString(int minute) {
        //如果传入的分钟是0，默认0分钟
        if (0 == minute) {
            return 0 + "分钟";
        }
        //如果分钟小于60，默认返回分钟
        if (0 < minute && minute < 60) {
            return minute + "分钟";
        }
        //如果分钟小于24小时（1440分钟），返回小时和分钟
        if (60 <= minute && minute < 1440) {

            if (minute % 60 == 0) {
                int h = minute / 60;
                return h + "小时";
            } else {
                int h = minute / 60;
                int m = minute % 60;
                return h + "小时" + m + "分钟";
            }

        }
        //如果分钟大于1天
        if (minute >= 1440) {

            int d = minute / 60 / 24;
            int h = minute / 60 % 24;
            int m = minute % 60;
            String s1 = null;
            if (d > 0) {
                s1 = d + "天";
            }
            //h如果计算大于等于1再展示，否则只展示天和分钟
            if (h >= 1) {
                s1 += h + "小时";
            }
            if (m > 0) {
                s1 += m + "分钟";
            }

            return s1;
        }
        return null;
    }

    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @author Eleven
     * @date 2021-04-07 11:11
     * @return date1-date2相差天数
     */
    public static int differentDays(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) {
            //不同一年
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                    //闰年
                    timeDistance += 366;
                } else {
                    //不是闰年
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2 - day1);
        } else {
            //同一年
            return day2 - day1;
        }
    }
}
